package main

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

// ==== 注解定义（其实就是 tag 规则） ====
type Validator func(f reflect.StructField, v reflect.Value) error

var registry = map[string]Validator{
	"notnull": validateNotNull,
	"range":   validateRange,
}

// ==== 具体校验器 ====
func validateNotNull(f reflect.StructField, v reflect.Value) error {
	if isZero(v) {
		return fmt.Errorf("field %q must not be null", f.Name)
	}
	return nil
}

func validateRange(f reflect.StructField, v reflect.Value) error {
	tag := f.Tag.Get("range")
	if tag == "" {
		return nil
	}
	parts := strings.Split(tag, ",")
	min, _ := strconv.ParseInt(parts[0], 10, 64)
	max, _ := strconv.ParseInt(parts[1], 10, 64)

	if v.Kind() >= reflect.Int && v.Kind() <= reflect.Int64 {
		val := v.Int()
		if val < min || val > max {
			return fmt.Errorf("field %q out of range [%d,%d]", f.Name, min, max)
		}
	}
	return nil
}

// ==== 统一入口 ====
func Validate(obj interface{}) []error {
	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
		v = v.Elem()
	}
	var errs []error
	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		fv := v.Field(i)
		// 逐个注解执行
		for key, vf := range registry {
			if _, ok := f.Tag.Lookup(key); ok {
				if err := vf(f, fv); err != nil {
					errs = append(errs, err)
				}
			}
		}
	}
	return errs
}

// ==== 工具 ====
func isZero(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.String:
		return v.String() == ""
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Ptr, reflect.Slice, reflect.Map:
		return v.IsNil()
	}
	return false
}

// ==== 使用示例 ====
type User struct {
	Name string `notnull`
	Age  int    `range:"1,120"`
}

func main() {
	u1 := User{Name: "Bob", Age: 30}
	if errs := Validate(u1); len(errs) == 0 {
		fmt.Println("✅ u1 合法")
	}

	u2 := User{Name: "", Age: 150} // 两个注解都挂
	for _, e := range Validate(u2) {
		fmt.Println("❌", e)
	}
}